package com.example.yanke.printer;

import android.content.Context;
import android.content.SharedPreferences;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import com.example.yanke.printerc1.YKPrinterC1Manager;
import com.telpo.tps550.api.printer.UsbThermalPrinter;
import com.telpo.tps550.api.util.ShellUtils;

import java.util.concurrent.ArrayBlockingQueue;

import static android.content.Context.MODE_PRIVATE;

/**
 * Created By kzz on 2021/8/16
 * Describe:
 */
public class YKPrinterManager {

    private final int INIT_ERROR = 1;
    private Context mContext;
    private UsbThermalPrinter mPrinter;
    private String[] portNum = new String[20];
    private String[] productNum = new String[20];
    private String[] readerNum = new String[4];
    private SharedPreferences preference;
    private SharedPreferences.Editor editor;
    private MyHandler handler;
    private String TAG = "YKPrinterManager";
    private static YKPrinterManager instance = null;
    private boolean isConnect;
    private ConnectThread connectThread;
    private ArrayBlockingQueue<YKPrinterListener> listenerQueue;
    private YKPrinterListener mYKPrinterListener;

    private YKPrinterManager(Context context) {
        this.mContext = context;
        this.mPrinter = new UsbThermalPrinter(mContext);
        preference = mContext.getSharedPreferences("TPS390PRINTER", MODE_PRIVATE);
        editor = preference.edit();
        handler = new MyHandler();
        listenerQueue = new ArrayBlockingQueue<>(100);
        connectThread = new ConnectThread();
        connectThread.start();
    }

    public static YKPrinterManager getInstance(Context context) {
        if (instance == null) {
            synchronized (YKPrinterC1Manager.class) {
                if (instance == null) {
                    instance = new YKPrinterManager(context);
                }
            }
        }
        return instance;
    }

    public void initPrinter(YKPrinterListener mYKPrinterListener) {
        listenerQueue.offer(mYKPrinterListener);
    }

    private class MyHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case INIT_ERROR://打印异常
                    if (mYKPrinterListener!=null)
                        mYKPrinterListener.initError((String) msg.obj);
                    break;
                default:
                    break;
            }
        }
    }

    private class ConnectThread extends Thread {

        boolean isInterrupt;

        @Override
        public void run() {
            while (!isInterrupt) {
                try {
                    if (!isConnect) {
                        String temp = getUsbPrinterDev();
                        Log.d(TAG, "getUsbPrinterDev():" + temp);
                        Log.d(TAG, "preference:" + preference.getString("usbPrinterDev", "-1"));
                        if (temp.equals("-2") || !temp.equals(preference.getString("usbPrinterDev", "-1"))) {
                            mPrinter.stop();
                            Thread.sleep(250);
                            mPrinter.start(0);
                        }
                        isConnect = true;
                    }
                    mYKPrinterListener= listenerQueue.take();
                    mYKPrinterListener.initSuccess(mPrinter);

                } catch (Exception e) {
                    e.printStackTrace();
                    String result = e.toString();
                    if (result.equals("com.telpo.tps550.api.printer.NoPaperException")) {
                        handler.sendMessage(handler.obtainMessage(INIT_ERROR, "没有打印纸"));
                    } else if (result.equals("com.telpo.tps550.api.printer.OverHeatException")) {
                        handler.sendMessage(handler.obtainMessage(INIT_ERROR, "打印过热"));
                    } else {
                        handler.sendMessage(handler.obtainMessage(INIT_ERROR, "打印异常"));
                    }
                    Log.d(TAG, "打印异常：" + result);
                }
            }
        }

        @Override
        public void interrupt() {
            isInterrupt = true;
            super.interrupt();
        }
    }

    private String getUsbPrinterDev() {
        String msgSuccess = ShellUtils.execCommand("cat /proc/bus/usb/devices", false).successMsg;
        searchAllIndex(msgSuccess, "Dev#=", 1);
        searchAllIndex(msgSuccess, "Product=", 2);
        return checkPort(portNum, productNum);
    }

    private void searchAllIndex(String str, String key, int type) {
        if (str != null && !str.equals("")) {
            int a = str.indexOf(key);
            int i = -1;
            while (a != -1) {
                i++;
                if (type == 1) {
                    portNum[i] = str.substring(a + 5, a + 8);
                    Log.d("idcard demo", "portNum[" + i + "]:" + portNum[i]);
                } else if (type == 2) {
                    productNum[i] = str.substring(a + 8, a + 27);
                    Log.d("idcard demo", "portNum[" + i + "]:" + portNum[i]);
                }
                a = str.indexOf(key, a + 1);
            }
        }
    }

    private String checkPort(String[] port, String[] product) {
        int k = -1;
        for (int i = 0; i < 20; i++) {
            if (productNum[i] != null && productNum[i].equals("USB Thermal Printer")) {
                k++;
                readerNum[k] = portNum[i];
                Log.d("idcard demo", "readnum[]:" + readerNum[k]);
                editor.putString("usbPrinterDev", readerNum[k]);
                editor.commit();
                return readerNum[k];
            }
        }
        editor.putString("usbPrinterDev", "-2");
        editor.commit();
        return "-2";
    }

    /**
     * 释放资源(打印中不要调用此方法，不然打印会停止)
     */
    public void releasePrint() {
        if (handler != null)
            handler.removeCallbacksAndMessages(null);
        if (mPrinter != null)
            mPrinter.stop();
        instance = null;
        isConnect = false;
        if (connectThread!=null) {
            connectThread.isInterrupt = true;
            connectThread.interrupt();
        }
    }
}
